﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Gene
{
    class Fungsi
    {
        public static List<int> get_key(String pass)
        {
            List<int> key = new List<int>();
            int i, j = 1, k, lp, lt, delta = 0, start = 0, f1 = 0, f2 = 0, mod = 0, M = 256;
            lp = pass.Length;
            for (i = 0; i < lp; ++i)
            {
                mod += (pass[i] + 1);
                start += (pass[i] * j);
                delta += (pass[i] * j * (i + 1));
                k = 0;
                for (j = 0; j < lp && j < 5; ++j)
                    k = k + pass[i + j] * (j + 1) + 1;
                f1 += k;
                k = 0;
                for (j = 0; j < lp && j < 6; ++j)
                    k = k + (pass[i + j] << (8 - j)) + 2;
                f2 += k;
                j = 0 - j;
            }
            key.Add(start);
            key.Add(f1);
            key.Add(f2);
            key.Add(mod);
            key.Add(M);
            return key;
        }

        public static string Encrypt(int start, int f1, int f2, int mod, int M, string s)
        {
	        int i, j, k, l=0, length=s.Length, awal, akhir, Length, temp, f3;
	        string hasil = "";
	        int []next = new int[length];
	
	        start = ((start % length) + length) % length;
	        for (i=1; i<length-1; ++i)
		        next[i] = i+1;
	        if (length>=2)
	        {
		        next[0] = 1;
		        next[length-1] = 0;
	        }
	        else
		        next[0] = 0;
	        awal = 0;
	        akhir = length-1;
	
	        Length=length-1;
	        for (i=0; i<length; ++i)
	        {
		        temp = start;
		        if (i<length-1)
		        {
			        start = ((start + f1 % mod) % Length + Length) % Length;
			        Length=(length-i-2);
		        }
		        k = awal;
		        for (j=0; j<temp; ++j)
		        {
			        l = k;
			        k = next[k];
		        }
		        if (k==awal)
		        {
			        next[akhir] = next[k];
			        awal = next[k];
		        }
		        else if (k==akhir)
		        {
			        next[l] = awal;
			        akhir = l;
		        }
		        else
			        next[l] = next[k];
		        hasil += (char)((((s[k] + f1) % 256 ) % 256)^f1);
		        f3 = (f1 + f2) % M;
		        f1 = f2;
		        f2 = f3;
	        }
	        return hasil;
        }

        string Decrypt(int start, int f1, int f2, int mod, int M, string s)
        {
	        int i, j, k, l=0, length = s.Length, awal, akhir, Length, temp, f3;
	        char []hasil = new char[length+1];
	        int []next = new int[length];
	
	        start = ((start % length) + length) % length;
	        for (i=1; i<length-1; ++i)
		        next[i] = i+1;
	        if (length>=2)
	        {
		        next[0] = 1;
		        next[length-1] = 0;
	        }
	        else
		        next[0] = 0;
	        awal = 0;
	        akhir = length-1;
	
	        Length=length-1;
	        for (i=0; i<length; ++i)
	        {
		        temp = start;
		        if (i<length-1)
		        {
			        start = ((start + f1 % mod) % Length + Length) % Length;
			        Length=(length-i-2);
		        }
		        k = awal;
		        for (j=0; j<temp; ++j)
		        {
			        l = k;
			        k = next[k];
		        }
		        if (k==awal)
		        {
			        next[akhir] = next[k];
			        awal = next[k];
		        }
		        else if (k==akhir)
		        {
			        next[l] = awal;
			        akhir = l;
		        }
		        else
			        next[l] = next[k];
		        hasil[k] = (char)((((((int)s[i])^f1)- f1) % 256 ) % 256);
		        f3 = (f1 + f2) % M;
		        f1 = f2;
		        f2 = f3;
	        }
	        hasil[length] = (char)0;
	        return hasil.ToString();
        }
    }
}
